package edu.cmu.javadb.plan.visitor;

import java.util.*;

import edu.cmu.javadb.QueryableSet;
import edu.cmu.javadb.VCollection;
import edu.cmu.javadb.exceptions.NotFlattenableException;
import edu.cmu.javadb.exceptions.NotProjectableException;
import edu.cmu.javadb.plan.*;

public class ExecutionVisitor implements Visitor<QueryableSet<?>> {

	@Override
	public QueryableSet<?> visitNode(Join node) {
		return node.getLeft().accept(this).join(node.getRight().accept(this), node.getLeftColumn(), node.getRightColumn());
	}

	@Override
	public QueryableSet<?> visitNode(Selection node) {
		PlanNode child = node.getChild();
		if (child instanceof Table) {
			Table t = (Table) child;
			if (t.getTable() instanceof VCollection) {
				VCollection<?> vc = (VCollection<?>) t.getTable();
				QueryableSet<?> res = new QueryableSet<Object>();
				res.addAll((Collection) vc.query(node.getCondition()));
				return res;
			}
		}
		
		return node.getChild().accept(this).filter(node.getCondition());
	}

	@Override
	public QueryableSet<?> visitNode(Table node) {
		QueryableSet<Object> res = new QueryableSet<Object>();
		res.addAll(node.getTable().execute());
		return res;
	}

	@Override
	public QueryableSet<?> visitNode(Union node) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryableSet<?> visitNode(Flattenation node) {
		try {
			return node.getChild().accept(this).flatten();
		} catch (NotFlattenableException e) {
			e.printStackTrace();
			return null;
		}
	}

	@Override
	public QueryableSet<?> visitNode(Projection node) {
		if (node.getColumns().size() == 1) {
			try {
				return node.getChild().accept(this).project(node.getColumns().get(0));
			} catch (NotProjectableException e) {
				e.printStackTrace();
			
			}
		} else {
			//TODO add more stuff after the optimizater is added
		}
		return null;
	}
}
